package com.djsearch.data;


import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.widget.ImageView;

/**
 * 异步请求图片类
 * 主要用于listview加载图片
 * @author chenyang2
 *
 */
public class RequestImage {
	private static final String LOG_TAG = "ImageDownloader";
	private static Bitmap m_DefaultBmp = null;//设置的默认图片
	private static final int HARD_CACHE_CAPACITY = 30;
	private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
	private static RequestImage requestImage;
	private static String pathImg;
	public RequestImage(Bitmap defaultbmp) {
		m_DefaultBmp = defaultbmp; 
	}
	
	/**
	 * 单例获取该类
	 * @param defaultbmp
	 * @return
	 */
	public static RequestImage getIntance(Bitmap defaultbmp,String path) {
		if (requestImage == null) {
			requestImage = new RequestImage(defaultbmp);
		}
		pathImg = path;
		m_DefaultBmp = defaultbmp;
		return requestImage;
	}
	
	/**
	 * 加载图片方法入口
	 */
	
	public  void download(String url, ImageView imageView){    
		resetPurgeTimer();
		Bitmap bitmap = getBitmapFromCache(url);
		if (bitmap == null) {
			//检查下sd卡
			bitmap = ImageManager.readImgFromSDcard(pathImg,url);
		}
		if (bitmap == null) {
			forceDownload(url, imageView);
		} else {
			cancelPotentialDownload(url, imageView);
			imageView.setImageBitmap(ImageManager.resizeImage(bitmap,150.0f));
		}
	}
   
	/**
	 * 开始加载图片,从网络加载
	 * @param url
	 * @param imageView
	 */
	private void forceDownload(String url, ImageView imageView){
		if (url == null) {
			//设置默认图片
			imageView.setImageBitmap(m_DefaultBmp);
			return;
		}
		if (cancelPotentialDownload(url, imageView)) {
			
			BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
			DownloadedDrawable downloadedDrawable = new DownloadedDrawable(m_DefaultBmp,task);
			imageView.setImageDrawable(downloadedDrawable);        
			task.execute(url);
		}
	}  
	
	/**
	 * 但是当我们向下滑动一屏，再向上滑动回之前那一屏时，这个时候bitmapDownloaderTask 已不再为null. 
	 * 我们将bitmapDownloaderTask.url与参数中的url进行对比（这个时候注意：很明显参数中的url才是我们需要下载的url）：
	 * 如果不等，则停止正在下载的（因为这不是我们需要的），
	 * 返回true；如果相等，则返回false，继续当前的图片下载任务
	 * @param url
	 * @param imageView
	 * @return
	 */
	private  boolean cancelPotentialDownload(String url, ImageView imageView){
		
		BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
		if (bitmapDownloaderTask != null) {
			String bitmapUrl = bitmapDownloaderTask.url;
			if ((bitmapUrl == null) || (!bitmapUrl.equals(url))){
				bitmapDownloaderTask.cancel(true);
			} else {
				return false;
			}
		}
		return true;
	}

	/**
	 * 
	 * @param imageView
	 * @return
	 */
	private  BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
		if (imageView != null) {
			Drawable drawable = imageView.getDrawable();
			if (drawable instanceof DownloadedDrawable) {
				DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
				return downloadedDrawable.getBitmapDownloaderTask();
			}
		}
		return null;
	}

    /**
     * 异步加载图片任务类
     * @author chenyang2
     *
     */
	class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
		
		private String url;
		private final WeakReference<ImageView> imageViewReference;
		public BitmapDownloaderTask(ImageView imageView) {
			imageViewReference = new WeakReference<ImageView>(imageView);
		}
		@Override
		protected Bitmap doInBackground(String... params) {
			url = params[0];
			return loadImageFromUrl(url);
		}
		@Override
		protected void onPostExecute(Bitmap bitmap) {
			if (isCancelled()){
				bitmap = m_DefaultBmp;
			}
			addBitmapToCache(url, bitmap);
			if (imageViewReference != null) {
				ImageView imageView = imageViewReference.get();
				BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
				if ((this == bitmapDownloaderTask) ) {
					if(bitmap!=null) {
//						imageView.setImageBitmap(bitmap);	
						imageView.setImageBitmap(ImageManager.resizeImage(bitmap,150.0f));
					}
				}
			}
		}
	}

	/**
	 * 图片
	 * @author chenyang2
	 *
	 */
	 class DownloadedDrawable extends BitmapDrawable {
		 
		 private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
		 public DownloadedDrawable(Bitmap DefaultBmp,BitmapDownloaderTask bitmapDownloaderTask) {
			super(DefaultBmp);//设置默认图片
			bitmapDownloaderTaskReference =
				new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
		}
		public BitmapDownloaderTask getBitmapDownloaderTask() {
			return bitmapDownloaderTaskReference.get();
		}
	}

	/*public void setMode(Mode mode) 
	{
		this.mode = mode;
		clearCache();
	}*/

	

	// Hard cache, with a fixed maximum capacity and a life duration
	private final HashMap<String, Bitmap> sHardBitmapCache =
		new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
			private static final long serialVersionUID = 1L;

		@Override
		protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
			if (size() > HARD_CACHE_CAPACITY) {
				// Entries push-out of hard reference cache are transferred to soft reference cache
				sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
				return true;
			} else {
				return false;
			}
		}
		};

		// Soft cache for bitmaps kicked out of hard cache
		private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
			new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);

		private final Handler purgeHandler = new Handler();

		private final Runnable purger = new Runnable() {
			public void run() {
				clearCache();
			}
		};

        /**
         * 加入图片到缓存
         * @param url
         * @param bitmap
         */
		private void addBitmapToCache(String url, Bitmap bitmap) {
			if (bitmap != null){
				
				synchronized (sHardBitmapCache) {
					sHardBitmapCache.put(url, bitmap);
				}
			}
		}

		/**
		 * 从缓存获取图片
		 * @param url
		 * @return
		 */
		private Bitmap getBitmapFromCache(String url) {
			synchronized (sHardBitmapCache) {
				
				final Bitmap bitmap = sHardBitmapCache.get(url);
				if (bitmap != null){
					sHardBitmapCache.remove(url);
					sHardBitmapCache.put(url, bitmap);
					return bitmap;
				}
			}
			SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);
			if (bitmapReference != null) {
				final Bitmap bitmap = bitmapReference.get();
				if (bitmap != null) {
					return bitmap;
				} else {
					sSoftBitmapCache.remove(url);
				}
			}
			return null;
		} 

		/**
		 * 清除缓存
		 */
		public void clearCache() {
			sHardBitmapCache.clear();
			sSoftBitmapCache.clear();
		}

		public void RemoveCacheItem(String key) {
			sHardBitmapCache.remove(key);
			sSoftBitmapCache.remove(key);
		}
		private void resetPurgeTimer() {
			purgeHandler.removeCallbacks(purger);
			purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
		}
		
		/**
		 * 从网络读取图片
		 * @param url
		 * @return
		 */
		public  Bitmap loadImageFromUrl(String url) {
			URL m;
			Drawable d = null;
			InputStream i = null;
				try {
					m = new URL(url);
					if(m==null||m.openStream()==null){
						return null;
					}
					i = (InputStream) m.openStream();
				
				} catch (Exception e) {
					e.printStackTrace();
					if(i!=null) {
						try {
							i.close();
						} catch (IOException e1) {
							e1.printStackTrace();
							return null;
						}
					}
					return null;
				}
				try {
					d = Drawable.createFromStream(i, "src");
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
				if(i!=null) {
					try {
						i.close();
					} catch (IOException e) {
						e.printStackTrace();
						return null;
					}
				}
				BitmapDrawable bd = (BitmapDrawable) d;
				Bitmap bm = null;
				if (bd != null) {
					 bm = bd.getBitmap();
				}
				
				if (bm != null) {
					//将图片写入sd卡
					ImageManager.writeImgToSDcard(pathImg,url , bm);
				}
				return bm;
		}
		

}
